package interfaces.hud.targetInfos;

import interfaces.superWidgets.ListenerKeeperElement;
import logic.nodes.TeamNode;

import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.BlendState;

import fileHandling.TextureLoader;

public abstract class AbsTargetArrow extends TargetInfoNode {
	
	protected static final long serialVersionUID = 1L;
	
	protected static final String arrowPath = "data/textures/hud/targetArrows/";
	protected static final String ARROW_FILE = arrowPath + "arrow";
	protected static final String TEAM_ARROW = ARROW_FILE + "_friend.png";
	protected static final String ENEMY_ARROW = ARROW_FILE + "_enemy.png";
	protected static final String MISSION_ARROW = ARROW_FILE + "_mission.png";
	
	public static final int DEFAULT_SIZE = 25;
	public static final int MARKED_SIZE = 50;
	
	protected int currentSize;
	protected Vector3f screenCenter;
	protected Quad arrow;
	protected boolean isMissionArrow;
	
	public AbsTargetArrow(TeamNode target, boolean isMissionArrow, ListenerKeeperElement element) {
		super("Arrow Node", target, element);
		this.isMissionArrow = isMissionArrow;
		
		if(isMissionArrow) arrow.setRenderState(TextureLoader.getTextureState(MISSION_ARROW));
	}
	
	@Override
	protected void init() {
		arrow = new Quad("targetArrow", DEFAULT_SIZE, DEFAULT_SIZE);
		arrow.setRenderQueueMode(Renderer.QUEUE_ORTHO);
				
		BlendState bs = display.getRenderer().createBlendState();
		bs.setBlendEnabled(true);
		bs.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
		bs.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
		bs.setTestEnabled(true);
		bs.setTestFunction(BlendState.TestFunction.GreaterThan);
		arrow.setRenderState(bs);
		
		arrow.setLightCombineMode(LightCombineMode.Off);
		arrow.updateRenderState();
		
		String arrowPath = (isFriendly ? TEAM_ARROW : ENEMY_ARROW);
		if(isMissionArrow) arrowPath = MISSION_ARROW;
		arrow.setRenderState(TextureLoader.getTextureState(arrowPath));
		
		setIsCollidable(false);
		
		currentSize = DEFAULT_SIZE;
	}
	
	@Override
	public void teamChanged() {
		super.teamChanged();
		
		detachChild(arrow);
		
		init();
	}
	
	@Override
	public void setMarked(boolean marked) {
		super.setMarked(marked);
		if(marked) currentSize = MARKED_SIZE;
		else currentSize = DEFAULT_SIZE;
		arrow.resize(currentSize, currentSize);
		updateRenderState();
	}
	
	protected abstract Vector3f getTargetLocation();
	
	@Override
	public void update() {
		if(getTargetLocation() == null) {
			arrow.removeFromParent();
			return;
		}
		
		Vector3f screenPos = display.getScreenCoordinates(getTargetLocation());
		if(screenPos.x > 0f && screenPos.x < display.getWidth() 
		&& screenPos.y > 0f && screenPos.y < display.getHeight() && screenPos.z < 1f) {
			arrow.removeFromParent();
			return;
		}
		
		boolean inverse = screenPos.z > 1f;
		
		screenPos.z = 0f;
		if(arrow.getParent() == null) attachChild(arrow);
		
		screenCenter = new Vector3f(display.getWidth() / 2f, display.getHeight() / 2f, 0f);
		Vector3f dir = screenPos.subtract(screenCenter);
		if(inverse) dir.negateLocal();
		arrow.rotateUpTo(dir.normalizeLocal());
		dir.multLocal(display.getWidth() / 2f - currentSize);
		
		Vector3f newPos = screenCenter.add(dir);
		checkBoundaries(newPos);
		
		arrow.getLocalTranslation().set(newPos);
	}
	
	protected void checkBoundaries(Vector3f pos) {
		if(pos.x < currentSize) pos.x = currentSize;
		if(pos.x > display.getWidth() - currentSize) pos.x = display.getWidth() - currentSize;
		
		if(pos.y < currentSize) pos.y = currentSize;
		if(pos.y > display.getHeight() - currentSize) pos.y = display.getHeight() - currentSize;
	}
}